/**
    @file        sample_app_mcal_icu_task.c
    @version     1.0.4

    @brief       AUTOSAR - Autosar  Sample Application.
    @details     Sample application using AutoSar MCAL drivers.

    Project      : AUTOSAR 4.0 MCAL
    Platform     : ARM

    Autosar Version       : 4.0.3
    Autosar Revision      : ASR_REL_4_0_REV_0003
    Autosar Conf. Variant :
    Software Version      : 1.0.4
    Build Version         : S32K14X_MCAL_1_0_4_RTM_ASR_REL_4_0_REV_0003_20190307

    (c) Copyright 2019 NXP
    All Rights Reserved.

    This file contains sample code only. It is not part of the production code deliverables.*/
/*==================================================================================================
==================================================================================================*/

#ifdef __cplusplus
extern "C"{
#endif

/*==================================================================================================
                                         INCLUDE FILES
 1) system and project includes
 2) needed interfaces from external units
 3) internal and external interfaces from this unit
==================================================================================================*/

#include "sample_app_mcal_icu_task.h"
#if (USE_ICU_MODULE==STD_ON)
#include "Icu_Cfg.h"
#endif  /* USE_ICU_MODULE==STD_ON */

/*==================================================================================================
                                        LOCAL MACROS
==================================================================================================*/


/*==================================================================================================
                                      FILE VERSION CHECKS
==================================================================================================*/


/*==================================================================================================
                          LOCAL TYPEDEFS (STRUCTURES, UNIONS, ENUMS)
==================================================================================================*/


/*==================================================================================================
                                       LOCAL CONSTANTS
==================================================================================================*/

/*==================================================================================================
                                       LOCAL VARIABLES
==================================================================================================*/
static volatile uint8 SampleApp_IcuOverflow = 0u;
static VAR(uint16, AUTOMATIC) SampleApp_IcuOldValue = 0U;
/*==================================================================================================
                                       GLOBAL CONSTANTS
==================================================================================================*/


/*==================================================================================================
                                       GLOBAL VARIABLES
==================================================================================================*/


/*==================================================================================================
                                   LOCAL FUNCTION PROTOTYPES
==================================================================================================*/


/*==================================================================================================
                                       LOCAL FUNCTIONS
==================================================================================================*/


/*==================================================================================================
                                       GLOBAL FUNCTIONS
==================================================================================================*/

#if (USE_ICU_MODULE==STD_ON)
/**
@brief      Sampleapp_Icu_Overflow - Overflow notification function for channel Pwm_measure
@details    This notification is used to update overflow error generated by the Icu

@return     void

@pre None
@post None
*/
void Sampleapp_Icu_Overflow(void)
{
    SampleApp_IcuOverflow = 1;
    Icu_GetInputState(IcuChannelName);
}
/**
@brief      SampleAppIcuInit - Initialize the Icu task
@details    After calling this function the task containing Icu should be initialize

@return     Returns the value of success
@retval     E_OK or E_NOT_OK

@pre None
@post None
*/
/*================================================================================================*/
FUNC (Std_ReturnType, SAMPLE_APP_CODE) SampleAppIcuInit(P2VAR(SampleAppData_T, AUTOMATIC, SAMPLE_APP_VAR) pstSampleAppData)
{
    Std_ReturnType stdRet = E_OK;

    pstSampleAppData->stIcuData.pIcuDriverConfig = (Icu_ConfigType *)(&IcuConfigSetName);

    /* Initialize the PWM with the post build configuration pointer */
    Icu_Init(pstSampleAppData->stIcuData.pIcuDriverConfig);

    pstSampleAppData->stIcuData.ucState = ICU_INITIAL_STATE;

    return stdRet;
}
#endif  /* USE_ICU_MODULE==STD_ON */


#if ((USE_ICU_MODULE==STD_ON) && (USE_ADC_MODULE==STD_ON) && (USE_PWM_MODULE==STD_ON))
/**
@brief      SampleAppIcuTask - Contains the Icu task
@details

@return     Returns the value of success of executing the Icu task
@retval     E_OK or E_NOT_OK

@pre None
@post None
*/
/*================================================================================================*/
FUNC (Std_ReturnType, SAMPLE_APP_CODE) SampleAppIcuTask(P2VAR(SampleAppData_T, AUTOMATIC, SAMPLE_APP_VAR) pstSampleAppData)
{
    Std_ReturnType stdRet = E_OK;
    VAR(Icu_DutyCycleType, AUTOMATIC) sigDutyCycle;
    volatile VAR (uint32, AUTOMATIC) IcuValueDutyCycle = 0;
    volatile VAR (uint32, AUTOMATIC) AdcPercentageValue = 0;
    volatile VAR (uint32, AUTOMATIC) tol_positive = 0;

    /* ICU state machine */
    switch(pstSampleAppData->stIcuData.ucState)
    {

        case ICU_FINISHED_MEASUREMENT_STATE:
        {
            /* if the pwm_state was changed in complete, icu state can be also changed */
            if (PWM_COMPLETE_STATE == pstSampleAppData->stPwmData.ucState)
            {
                IcuValueDutyCycle  = (uint32)((uint32)(pstSampleAppData->stIcuData.IcuDuty.ActiveTime * 100UL)) / (uint32)pstSampleAppData->stIcuData.IcuDuty.PeriodTime;
                AdcPercentageValue = (uint32)(((uint32)(pstSampleAppData->stAdcData.usValueConverted * 100UL)) >> SAMPLE_ADC_BITS_RESOLUTION);

                tol_positive = IcuValueDutyCycle < AdcPercentageValue ? (AdcPercentageValue - IcuValueDutyCycle) : (IcuValueDutyCycle - AdcPercentageValue);

                if (tol_positive > ICU_THRESHOLD)
                {
                    pstSampleAppData->stIcuData.ucState = ICU_ERROR_STATE;
                    CONSOLE_MESSAGE("ICU Error: Duty cycle measured by ICU, was not the one set up using the value on ADC", 0);
                    stdRet = E_NOT_OK;
                    break;
                }
                else
                {
                    pstSampleAppData->stIcuData.ucState = ICU_COMPLETE_STATE;
        
                }                
            }
            else
            {
                break;
            }
        }
        case ICU_COMPLETE_STATE:
        {/* Set up initial states to Adc, Pwm, Icu state machine */
            pstSampleAppData->stAdcData.ucState = ADC_INITIAL_STATE;
            pstSampleAppData->stPwmData.ucState = PWM_INITIAL_STATE;
            pstSampleAppData->stIcuData.ucState = ICU_INITIAL_STATE;
			/*print console message only if the ADC (input value) was changed*/
			IcuValueDutyCycle  = (uint32)(((uint32)pstSampleAppData->stIcuData.IcuDuty.ActiveTime * 100UL) / (uint32)pstSampleAppData->stIcuData.IcuDuty.PeriodTime);
			if (TRUE == pstSampleAppData->stAdcData.bValueWasUpdated)
                {    
				 CONSOLE_MESSAGE("ICU Test passed! Measured PWM duty Value in percent:", IcuValueDutyCycle);
                 pstSampleAppData->stAdcData.bValueWasUpdated = FALSE;
                } 		
			break;
		}
        case ICU_INITIAL_STATE:
            stdRet = E_OK;
            break;
        
        case ICU_RUNNING_STATE:
        {
            if (ICU_ACTIVE == Icu_GetInputState(IcuChannelName))
            {
                if (0 == SampleApp_IcuOverflow)
                {
                    Icu_GetDutyCycleValues(IcuChannelName, &sigDutyCycle);
                    pstSampleAppData->stIcuData.IcuDuty.ActiveTime = sigDutyCycle.ActiveTime;
                    pstSampleAppData->stIcuData.IcuDuty.PeriodTime = sigDutyCycle.PeriodTime;

                    if (sigDutyCycle.ActiveTime == 0)
                    {
                        Icu_StopSignalMeasurement(IcuChannelName);
                        Icu_StartSignalMeasurement(IcuChannelName);

                        /*CONSOLE_MESSAGE("ICU Error: Wrong value measured for Duty Cycle.", 0);*/
                        /*stdRet = E_NOT_OK;*/
                        break;
                    }
                    else
                    {
                        IcuValueDutyCycle  = (uint32)(((uint32)sigDutyCycle.ActiveTime * 100UL) / (uint32)pstSampleAppData->stIcuData.IcuDuty.PeriodTime);
                        AdcPercentageValue = (uint32)((pstSampleAppData->stAdcData.usValueConverted * 100UL) >> SAMPLE_ADC_BITS_RESOLUTION);

                        tol_positive = IcuValueDutyCycle < AdcPercentageValue ? (AdcPercentageValue - IcuValueDutyCycle) : (IcuValueDutyCycle - AdcPercentageValue);

                        if (tol_positive <= ICU_THRESHOLD)
                        {
                            pstSampleAppData->stIcuData.ucState = ICU_COMPLETE_STATE;
                            Icu_StopSignalMeasurement(IcuChannelName);
                        }
                        else
                        {
                            Icu_StopSignalMeasurement(IcuChannelName);
                            Icu_StartSignalMeasurement(IcuChannelName);
                        }
                    }
                }
                else
                {
                    SampleApp_IcuOverflow = 0;
                }
            }
            stdRet = E_OK;            
            break;
        }
        case ICU_ERROR_STATE:
            stdRet = E_NOT_OK;
            break;

        default:
            stdRet = E_NOT_OK;
            break;

    }
    return (stdRet);
}
#endif  /* USE_ICU_MODULE==STD_ON */

/*================================================================================================*/
/*================================================================================================*/
#ifdef __cplusplus
}
#endif
